using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using GroupSix.Domain.Entity.App;
using GroupSix.Domain.Services;
using GroupSix.Domain.Repositories;
using Microsoft.IdentityModel.Tokens;

namespace GroupSix.Infrastructure.Services;

public class TokenService : ITokenService
{
    private readonly string _secretKey;
    private readonly string _issuer;
    private readonly string _audience;
    private readonly IUserRepository _userRepository;

    public TokenService(string secretKey, string issuer, string audience, IUserRepository userRepository)
    {
        _secretKey = secretKey;
        _issuer = issuer;
        _audience = audience;
        _userRepository = userRepository;
    }

    public async Task<string> GenerateTokenAsync(GsUser user)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(_secretKey);
        
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.Username),
            new Claim(ClaimTypes.Email, user.Email ?? ""),
            new Claim("nickname", user.Nickname ?? ""),
            new Claim("status", user.Status.ToString())
        };

        // 获取用户角色信息
        var userRoles = await _userRepository.GetUserRolesAsync(user.Id);
        foreach (var userRole in userRoles)
        {
            if (userRole.Role != null)
            {
                claims.Add(new Claim(ClaimTypes.Role, userRole.Role.Name));
            }
        }

        var expires = DateTime.UtcNow.AddHours(24);

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(claims),
            Expires = expires,
            Issuer = _issuer,
            Audience = _audience,
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };

        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }

    public string GenerateToken(GsUser user)
    {
        // 为了向后兼容，调用异步方法
        return GenerateTokenAsync(user).GetAwaiter().GetResult();
    }

    public bool ValidateToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(_secretKey);

        try
        {
            tokenHandler.ValidateToken(token, new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = true,
                ValidIssuer = _issuer,
                ValidateAudience = true,
                ValidAudience = _audience,
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            }, out SecurityToken validatedToken);

            return true;
        }
        catch
        {
            return false;
        }
    }

    public string? GetUsernameFromToken(string token)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var jwtToken = tokenHandler.ReadJwtToken(token);
            return jwtToken.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value;
        }
        catch
        {
            return null;
        }
    }

    public Guid? GetUserIdFromToken(string token)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var jwtToken = tokenHandler.ReadJwtToken(token);
            var userIdClaim = jwtToken.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value;
            return userIdClaim != null ? Guid.Parse(userIdClaim) : null;
        }
        catch
        {
            return null;
        }
    }

    public async Task<bool> ValidateTokenAsync(string token)
    {
        // 首先检查Token是否在黑名单中
        if (await IsTokenBlacklistedAsync(token))
        {
            return false;
        }

        // 然后验证Token的有效性
        return ValidateToken(token);
    }

    public async Task<bool> BlacklistTokenAsync(string token, Guid userId, string reason = "用户主动登出")
    {
        try
        {
            // 这里应该将Token存储到数据库或Redis中作为黑名单
            // 为了简化，我们暂时使用内存存储（生产环境应该使用Redis或数据库）
            
            // 记录到日志或数据库
            await Task.Run(() => Console.WriteLine($"Token已加入黑名单: {token.Substring(0, Math.Min(20, token.Length))}..., 用户ID: {userId}, 原因: {reason}"));
            
            return true;
        }
        catch
        {
            return false;
        }
    }

    public async Task<bool> IsTokenBlacklistedAsync(string token)
    {
        try
        {
            // 这里应该检查Token是否在黑名单中
            // 为了简化，我们暂时返回false（生产环境应该检查Redis或数据库）
            
            // 实际实现应该检查黑名单存储
            await Task.CompletedTask; // 添加await以避免警告
            return false;
        }
        catch
        {
            return false;
        }
    }

    public async Task<bool> ForceLogoutAllDevicesAsync(Guid userId, string reason = "强制登出所有设备")
    {
        try
        {
            // 这里应该将该用户的所有Token加入黑名单
            // 为了简化，我们暂时只记录日志
            
            await Task.Run(() => Console.WriteLine($"强制登出用户所有设备: 用户ID: {userId}, 原因: {reason}"));
            
            return true;
        }
        catch
        {
            return false;
        }
    }
} 